import os

from src.video.baseInfo.VideoFolderInfo import VideoFolderInfo
from src.video.baseInfo.VideoHeapsInfo import HeapInfo
from src.utils.file_utils import read_file
from src.utils.srt_utils import get_srt_texts_and_time_dict,get_videonode_from_srt,caculate_reduce_time,remove_heap_less_then_half,get_srt_texts,get_srt_info_from_index
from src.utils.text_utils import remove_non_chinese,remove_non_english_chars
from moviepy.editor import *
from moviepy.Clip import Clip
from typing import List
from src.utils.srt_utils import VideoNode
import random



class VideoCompositor():
    def __init__(self, video_folder_info: VideoFolderInfo, video_heap_list: List[HeapInfo], pic_num_per_second: int
                 ,save_temp_result = False,with_audio=False):
        self.videoFolderInfo = video_folder_info
        self.videoHeapList = video_heap_list
        self.picNumPerSecond = pic_num_per_second
        self.saveTempResult = save_temp_result
        self.with_audio = with_audio

    def _cut_movie_into_pieces(self,heap_time_left,final_save_name) -> List[Clip]:
        movie = VideoFileClip(self.videoFolderInfo.origin_mp4_file)
        if not self.with_audio:
            movie = movie.without_audio()


        subMovies = []

        randomList = [0, 0,0,1]
        currentSecond = 0
        before_end_index = 0
        after_start_index = 0

        before_left_second = 0
        for index, (heapInfo,new_time) in enumerate(zip(self.videoHeapList,heap_time_left)):
            start_position = heapInfo.max_relative_heap_inner_index
            if index == 44:
                j =0
            if index == 0:
                before_end_index =  0
                after_start_index = min(self.videoHeapList[index+1].max_relative_heap_index)

            elif index == len(self.videoHeapList) -1:
                before_end_index = max(self.videoHeapList[index - 1].max_relative_heap_index)
                after_start_index = 100000000
            else:
                before_end_index = max(self.videoHeapList[index - 1].max_relative_heap_index)
                after_start_index = min(self.videoHeapList[index+1].max_relative_heap_index)



            if new_time == 0:
                continue
            start_min = start_position /(self.picNumPerSecond +1)
            offset_time = 0
            random_start = 0

            left_capacity = (start_position - before_end_index -1)/(self.picNumPerSecond +1)
            right_capacity = (after_start_index - start_position -1)/(self.picNumPerSecond +1)
            if left_capacity <=0 or right_capacity <=0 :
                random_start = start_min
                offset_time = new_time + before_left_second
                before_left_second = 0
            else:
                if right_capacity >= before_left_second + new_time:
                    random_start = start_min
                    offset_time = new_time + before_left_second
                    before_left_second = 0
                elif right_capacity + left_capacity >= before_left_second + new_time:
                    random_start = start_min -((before_left_second + new_time) - right_capacity)
                    offset_time = new_time + before_left_second
                    before_left_second = 0
                else:
                    random_start = start_min - left_capacity
                    offset_time = left_capacity + right_capacity
                    before_left_second = new_time + before_left_second - offset_time

            if currentSecond == 0:
                subVideo = movie.subclip(random_start, random_start + offset_time)
            else:
                subVideo = movie.subclip(random_start, random_start + offset_time)

            # random_int = random.choice(randomList)
            # if random_int == 1:
            #     subVideo = subVideo.fx(vfx.mirror_x)

            if self.saveTempResult:
                if final_save_name  == self.videoFolderInfo.finalVideoName:
                    save_path = os.path.join(self.videoFolderInfo.jieshuoHeapSaveFolder, str(index) + ".mp4")
                else:
                    save_path = os.path.join(self.videoFolderInfo.jieshuoHeapSaveFolderEnglish, str(index) + ".mp4")
                subVideo.write_videofile(save_path,fps=32)
            if currentSecond == 0:
                subMovies.append(subVideo)
            else:
                subMovies.append(subVideo.set_start(currentSecond))
            currentSecond += offset_time
            print(currentSecond)
        return subMovies

    def reduce_time_list(self,old_srt_file, new_srt_file, old_2_new_convert_file,heap_seconds: List,saveFileName: str,heap_conver_file):
        '''
        根据convert_dict的映射关系，返回需要修剪的时间段
        :param old_srt_file: 原始解说对应的srt文件
        :param new_srt_file: 重写以后的解锁对应的srt文件
        :parm old_2_new_convert_file:原始解锁文本和重写以后的文本的映射关系
        :param heap_seconds: 原始解说每一个小段落heap对应的秒数秒数
        :param heap_conver_file: 解说heap对应的原始视频heap
        :return:
        '''
        old_srt_obj = get_srt_texts(old_srt_file)
        old_2_new_converts = read_file(old_2_new_convert_file, out_type='json')

        new_mp3_time_list = get_srt_texts_and_time_dict(new_srt_file)
        total = sum([i[1] for i in new_mp3_time_list])
        old_2_new_converts = self.update_time_into_dict(old_2_new_converts,new_mp3_time_list,saveFileName,old_srt_obj)

        heap_used_time = [0] * len(heap_seconds)
        heap_reduce_time = [0] * len(heap_seconds)
        current_heap_index = 0
        total = 0
        total_reduce = 0
        total_part =0
        for index, item in enumerate(old_2_new_converts):
            print(item['origin_srt_index'])
            total_part += len(item['origin_srt_index'])
            if item["origin_text"] != "":
                total += sum(item["new_srt_text_parts_time"])
            else:
                total_reduce += sum(item["new_srt_text_parts_time"])
        sum_heap_seconds = sum(heap_seconds)
        total_reduce = 0
        total_old = 0
        for index,item in enumerate(old_srt_obj):
            if item['index'] == -1:
                total_reduce += item["end"] - item['start']
            else:
                total_old += item["end"] - item['start']


        total = 0
        for index, item in enumerate(old_2_new_converts):
            print(total)
            print(sum(heap_reduce_time))
            if int(index) == 147:
                j = 1

            old_video_node = get_videonode_from_srt(old_srt_obj, item)
            if saveFileName == self.videoFolderInfo.finalVideoName:
                rewrite_text = item["rewrite"]
            else:
                rewrite_text = item["translate"]
            if rewrite_text:
                new_mp3_time = sum(item['new_srt_text_parts_time'])
                total += new_mp3_time
            else:
                new_mp3_time = 0

            if index == 0 and old_video_node.start != 0:
                first_video_node = VideoNode(0,old_video_node.start,old_video_node.start)
                current_heap_index = caculate_reduce_time(first_video_node, 0, heap_seconds,
                                                          current_heap_index,
                                                          heap_used_time, heap_reduce_time)


            current_heap_index = caculate_reduce_time(old_video_node, new_mp3_time, heap_seconds, current_heap_index,
                                                      heap_used_time, heap_reduce_time)
            print(current_heap_index)
            print("current_heap_used_time:"+ str(sum(heap_used_time)))
            print("current_old_srt_used_time:" + str(old_video_node.end))
            temp1 = sum(heap_reduce_time)
            j = 1




        heap_seconds_left = [a - b for a, b in zip(heap_seconds, heap_reduce_time)]
        total = sum(heap_reduce_time)
        #heap_seconds_left = remove_heap_less_then_half(heap_seconds_left)
        return heap_reduce_time


    def merge_pieces_into_video(self,sub_movies:List[Clip],save_name):
        # finalclip = CompositeVideoClip(sub_movies)

        with CompositeVideoClip(sub_movies) as video:
            video.write_videofile(save_name, threads=20)

    def process(self):
        heaps_len = [(i.heap_end - i.heap_start +1)/self.picNumPerSecond for i in self.videoHeapList]
        if not os.path.exists(self.videoFolderInfo.finalVideoName):
            target_jieshuo_srt_file = self.videoFolderInfo.jieshuo_srt_clean_file
            if os.path.exists(self.videoFolderInfo.jieshuo_srt_remove_dirty_file):
                target_jieshuo_srt_file = self.videoFolderInfo.jieshuo_srt_remove_dirty_file
            reduce_time_dict = self.reduce_time_list(old_srt_file=target_jieshuo_srt_file
                                                     ,new_srt_file=self.videoFolderInfo.jieshuoNewSrtPath
                                                     ,old_2_new_convert_file=self.videoFolderInfo.jieshuoSrtRewriteFileName
                                                     ,heap_seconds=heaps_len
                                                     ,saveFileName=self.videoFolderInfo.finalVideoName
                                                     ,heap_conver_file=self.videoFolderInfo.jieshuoHeapConvertFile)
            subMovies = self._cut_movie_into_pieces(reduce_time_dict,self.videoFolderInfo.finalVideoName)
            self.merge_pieces_into_video(subMovies,self.videoFolderInfo.finalVideoName)

        if not os.path.exists(self.videoFolderInfo.finalVideoNameEnglish):
            reduce_time_dict = self.reduce_time_list(old_srt_file=self.videoFolderInfo.jieshuo_srt_clean_file
                                                     , new_srt_file=self.videoFolderInfo.jieshuoNewSrtPathEnglish
                                                     ,old_2_new_convert_file=self.videoFolderInfo.jieshuoSrtRewriteFileName
                                                     , heap_seconds=heaps_len
                                                     ,saveFileName=self.videoFolderInfo.finalVideoNameEnglish
                                                     ,heap_conver_file=self.videoFolderInfo.jieshuoHeapConvertFile)
            subMovies = self._cut_movie_into_pieces(reduce_time_dict,self.videoFolderInfo.finalVideoNameEnglish)
            self.merge_pieces_into_video(subMovies, self.videoFolderInfo.finalVideoNameEnglish)

    def update_time_into_dict(self,info_list, srt_nodes_list,save_file,old_srt_obj):
        '''
        将srt_nodes_dict里面的时间和info_list里面关联起来
        :param info_list:
        :param srt_nodes_dict:
        :return:
        '''
        add_break_info_list = []
        index = 0
        for index_info, info in enumerate(info_list):
            if save_file == self.videoFolderInfo.finalVideoName:
                temp = remove_non_chinese(info['rewrite'])
            else:
                temp = remove_non_english_chars(info["translate"])
            info["new_srt_text_parts"] = []
            info["new_srt_text_parts_time"] = []
            while temp != "" and index < len(srt_nodes_list):
                if save_file == self.videoFolderInfo.finalVideoName:
                    check_text = remove_non_chinese(srt_nodes_list[index][0])
                else:
                    check_text = remove_non_english_chars(srt_nodes_list[index][0])
                if temp.startswith(check_text):
                    info["new_srt_text_parts"].append(check_text)
                    info["new_srt_text_parts_time"].append(srt_nodes_list[index][1])
                    temp = temp[len(check_text):]
                    index += 1
                elif temp[1:].startswith(check_text):
                    info["new_srt_text_parts"].append(check_text)
                    info["new_srt_text_parts_time"].append(srt_nodes_list[index][1])
                    temp = temp[len(check_text)+1:]
                    index += 1

            add_break_info_list.append(info)

            if 'break' in info and info['break'] == 1:
                break_info = {}
                break_info['origin_text'] = ""
                break_info['rewrite'] = ""
                if index_info + 1 < len(info_list):

                    next_node = info_list[index_info + 1]

                    break_start = get_srt_info_from_index(old_srt_obj,info['origin_srt_index'][-1])["end"]
                    break_end = get_srt_info_from_index(old_srt_obj,next_node['origin_srt_index'][0])["start"]
                    break_info['new_srt_text_parts_time'] = [break_end - break_start]
                    break_info["origin_srt_index"] = []
                    break_info["start"] = break_start
                    break_info["end"] = break_end
                    add_break_info_list.append(break_info)
        return add_break_info_list


